package com.dlc.shop.api.controller;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dlc.shop.bean.app.dto.*;
import com.dlc.shop.bean.app.vo.ProductVO;
import com.dlc.shop.bean.enums.ProdStatusEnums;
import com.dlc.shop.bean.enums.ProdType;
import com.dlc.shop.bean.enums.ShopStatus;
import com.dlc.shop.bean.event.*;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.bean.param.EsProductParam;
import com.dlc.shop.bean.param.ProductParam;
import com.dlc.shop.bean.vo.search.EsProductSearchVO;
import com.dlc.shop.bean.vo.search.ProductSearchVO;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.common.util.EsPageVO;
import com.dlc.shop.common.util.Json;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.delivery.common.model.SameCity;
import com.dlc.shop.delivery.common.service.SameCityService;
import com.dlc.shop.search.common.param.EsPageParam;
import com.dlc.shop.search.common.service.SearchProductService;
import com.dlc.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LGH
 */
@RestController
@RequestMapping("/prod")
@Tag(name = "商品接口")
@AllArgsConstructor
public class ProdController {

    private final ProductService prodService;
    private final CategoryService categoryService;
    private final SameCityService sameCityService;
    private final ApplicationContext applicationContext;
    private final SkuService skuService;
    private final ProdCommService prodCommService;
    private final ShopDetailService shopDetailService;
    private final ProdParameterService prodParameterService;
    private final SearchProductService searchProductService;
    private final ApplicationEventPublisher eventPublisher;


    @GetMapping("/prodInfo")
    @Operation(summary = "商品详情信息" , description = "根据商品ID（prodId）获取商品信息")
    @Parameter(name = "prodId", description = "商品ID" , required = true)
    public ServerResponseEntity<ProductVO> prodInfo(Long prodId, String userId, @RequestParam(name = "addrId", defaultValue = "0")Long addrId) {
        Product product = prodService.getProductInfo(prodId);
        if (product == null || product.getStatus() != 1) {
            // 商品已下线
            throw new YamiShopBindException("yami.product.off.shelves");
        }
        product.setProdLangList(null);
        // 检查店铺是否处于营业状态
        checkShopStatusIsOpen(product);
        // 启用的sku列表
        List<Sku> skuList = skuService.listPutOnSkuAndSkuStock(prodId,product.getMold());
        int sale = 0;
        int stock = 0;
        for (Sku sku : skuList) {
            sale += sku.getSaleNum();
            stock += sku.getStocks();
        }
        product.setSoldNum(sale);
        product.setTotalStocks(stock);
        product.setSkuList(skuList);
        ProductVO productVO = BeanUtil.map(product, ProductVO.class);
        if(Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_ACTIVE.value()) || productVO.getMold() == 1){
            productVO.setIsDelivery(true);
        }else{
            // 判断用户默认地址是否在配送区域内
            applicationContext.publishEvent(new CheckAddrEvent(addrId, userId, productVO, null));
        }
        //获取运费信息
        applicationContext.publishEvent(new CalculateTransfeeEvent(productVO, addrId, userId));
        // 如果是积分商品， 所有数据已经获取完成了
        if (Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_SCORE.value())) {
            return ServerResponseEntity.success(productVO);
        }
        // 发送事件，获取商品可用的正在开播直播间、商品套餐、秒杀、团购、店铺会员、积分商品信息
        applicationContext.publishEvent(new LoadProdActivistEvent(prodId, productVO, product.getProdType(), userId));
        // 普通商品有多种物流，需要加载物流模板信息
//        if (Objects.equals(productVO.getProdType(), ProdType.PROD_TYPE_NORMAL.value())) {
        loadDeliveryMode(product.getDeliveryMode(), productVO);
//        }
        // 商品参数列表
        List<ProdParameter> prodParameters = prodParameterService.listParameterByProdId(prodId);
        productVO.setProdParameterList(prodParameters);
        return ServerResponseEntity.success(productVO);
    }

    @GetMapping("/skuList")
    @Operation(summary = "sku信息" , description = "根据商品ID（prodId）单独获取sku信息")
    @Parameter(name = "prodId", description = "商品ID" , required = true)
    public ServerResponseEntity<List<SkuDto>> skuList(@RequestParam("prodId") Long prodId) {
        Product product = prodService.getProductByProdId(prodId);
        return ServerResponseEntity.success(skuService.getProdDetailSkuInfo(product));
    }

    @GetMapping("/isStatus")
    @Operation(summary = "校验商品是否下架" , description = "根据商品ID（prodId）校验商品是否下架")
    @Parameter(name = "prodId", description = "商品ID" , required = true)
    public ServerResponseEntity<Boolean> isStatus(Long prodId) {
        Product product = prodService.getProductByProdId(prodId);
        if (product == null || product.getStatus() != 1) {
            return ServerResponseEntity.success(false);
        }
        return ServerResponseEntity.success(true);
    }

    @GetMapping("/listProdByIdsAndType")
    @Operation(summary = "获取商品信息" , description = "根据商品ids获取商品信息")
    public ServerResponseEntity<List<ProductDto>> listProdByIdsAndType(ApiProdDto apiProdDto) {
        ProductParam productParam = BeanUtil.map(apiProdDto, ProductParam.class);
        apiProdDto.setLang(I18nMessage.getDbLang());
        apiProdDto.setStatus(ProdStatusEnums.NORMAL.getValue());
        List<Product> products = prodService.listProdByIdsAndType(productParam);
        processActivityProdPrice(productParam, products);
        List<ProductDto> productDtos = BeanUtil.mapAsList(products, ProductDto.class);
        return ServerResponseEntity.success(productDtos);
    }

    /**
     * 处理下活动商品的价格
     *
     * @param product  筛选参数
     * @param products 商品列表
     */
    private void processActivityProdPrice(ProductParam product, List<Product> products) {
        Map<Integer, List<Product>> prodMap = products.stream().collect(Collectors.groupingBy(Product::getProdType));
        if (prodMap.containsKey(ProdType.PROD_TYPE_SECKILL.value())) {
            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_SECKILL.value())));
        }

        if (prodMap.containsKey(ProdType.PROD_TYPE_GROUP.value())) {
            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_GROUP.value())));
        }
    }

    @GetMapping("/prodCommData")
    @Operation(summary = "返回商品评论数据(好评率 好评数量 中评数 差评数)" , description = "根据商品id获取")
    @Parameter(name = "prodId", description = "商品id" , required = true)
    public ServerResponseEntity<ProdCommDataDto> getProdCommData(Long prodId) {
        return ServerResponseEntity.success(prodCommService.getProdCommDataByProdId(prodId));
    }

    @GetMapping("/prodCommPageByProd")
    @Operation(summary = "根据商品返回评论分页数据" , description = "传入商品id和页码")
    @Parameters({
            @Parameter(name = "prodId", description = "商品id" , required = true),
            @Parameter(name = "evaluate", description = "-1或null 全部，0好评 1中评 2差评 3有图" , required = true),
    })
    public ServerResponseEntity<IPage<ProdCommDto>> getProdCommPageByProdId(PageParam page, Long prodId, Integer evaluate) {
        return ServerResponseEntity.success(prodCommService.getProdCommDtoPageByProdId(page, prodId, evaluate));
    }

    /**
     *  用户未登录情况下的商品推荐
     * @param page
     * @param productParam
     * @return
     */
    @GetMapping("/recommendList")
    @Operation(summary = "推荐商品列表" , description = "根据商品ID（prodId）获取商品信息")
    public ServerResponseEntity<EsPageVO<EsProductSearchVO>> recommendList(PageParam page, ProductParam productParam) {
        EsProductParam esProductParam = new EsProductParam();
        if (Objects.isNull(productParam.getProdType())) {
            esProductParam.setProdType(ProdType.PROD_TYPE_NORMAL.value());
        }
        Long primaryCategoryId = null;
        List<Category> categoryList = categoryService.getCategoryAndParent(productParam.getCategoryId());
        if (CollUtil.isNotEmpty(categoryList)) {
            primaryCategoryId = categoryList.get(0).getCategoryId();
        }
        esProductParam.setPrimaryCategoryId(primaryCategoryId);
        //如果有商品id则过滤掉
        if (Objects.nonNull(productParam.getProdId())) {
            List<Long> prodIds = new ArrayList<>();
            prodIds.add(productParam.getProdId());
            esProductParam.setSpuIdsExclude(prodIds);
        }
        EsPageParam esPageParam = new EsPageParam();
        esPageParam.setCurrent((int) page.getCurrent());
        esPageParam.setSize((int) page.getSize());
        EsPageVO<EsProductSearchVO> productPage = searchProductService.page(esPageParam, esProductParam, Boolean.FALSE);
        List<ProductSearchVO> products = productPage.getRecords().get(0).getProducts();
        long current = page.getCurrent();
        long size = page.getSize();
        int spuNum = products.size();
        // 推荐商品的数量不足时，查询额外的商品进行填充
        if (Objects.equals(current , 1L) && size > spuNum) {
            esPageParam.setSize(Math.toIntExact(size - spuNum));
            esPageParam.setCurrent(1);
            // 查询该分类以外的商品
            esProductParam.setPrimaryCategoryId(null);
            esProductParam.setNotPrimaryCategoryId(primaryCategoryId);
            EsPageVO<EsProductSearchVO> subProductPage = searchProductService.page(esPageParam, esProductParam, Boolean.FALSE);
            for (EsProductSearchVO productSearchVO : subProductPage.getRecords()) {
                if (CollUtil.isNotEmpty(productSearchVO.getProducts())) {
                    products.addAll(productSearchVO.getProducts());
                }
            }
            productPage.setTotal((long) products.size());
            productPage.setPages(productPage.getTotal() > 0 ? (int)page.getCurrent() : 0);
        }
        EsProductSearchVO esProductSearchVO = new EsProductSearchVO();
        esProductSearchVO.setProducts(products);
        if (StringUtil.isNotBlank(productParam.getUserId())) {
            eventPublisher.publishEvent(new LoadProdMemberPriceEvent(null, null, null, Collections.singletonList(esProductSearchVO), productParam.getUserId()));
        }
        return ServerResponseEntity.success(productPage);
    }

    private void checkShopStatusIsOpen(Product product) {
        // 积分商品的平台店铺不需要检验
        if (Objects.equals(product.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            return;
        }
        Date now = new Date();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(product.getShopId());
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN.value())) {
            return;
        }
        product.setShopName(shopDetail.getShopName());
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value()) || Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
            throw new YamiShopBindException("店铺已下线");
        }
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.STOP.value())) {
            if (now.compareTo(shopDetail.getContractStartTime()) < 0) {
                throw new YamiShopBindException("店铺未开始营业");
            } else {
                throw new YamiShopBindException("店铺已停止营业");
            }
        }
        throw new YamiShopBindException("店铺状态异常");
    }

    /**
     * 加载商品物流模板
     * @param deliveryMode
     * @param productVO
     */
    private void loadDeliveryMode(String deliveryMode, ProductVO productVO) {
        // 物流模板
        Product.DeliveryModeVO deliveryModeVO = Json.parseObject(deliveryMode, Product.DeliveryModeVO.class);
        SameCity sameCity = sameCityService.getSameCityByShopId(productVO.getShopId());
        // 如果同城配送是关闭了的，前端就不需要显示同城配送了
        if (Objects.isNull(sameCity) || !Objects.equals(1, sameCity.getStatus()) || Objects.isNull(deliveryModeVO.getHasCityDelivery())) {
            deliveryModeVO.setHasCityDelivery(false);
        }
        if (deliveryModeVO.getHasCityDelivery() != null && deliveryModeVO.getHasCityDelivery() && Objects.nonNull(sameCity)) {
            productVO.setStartDeliveryFee(sameCity.getStartingFee());
        }
        productVO.setDeliveryModeVO(deliveryModeVO);
    }
}
